import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM, Dense, Activation
from keras.callbacks import EarlyStopping

sequence_length = 10


#scaler = MinMaxScaler()
def load_data(file_name, split=0.8):
    df = pd.read_csv(file_name, sep=',', usecols=[1])
    data_all = np.array(df).astype(float)
    plt.plot(data_all)
    plt.show()
    #data_all = scaler.fit_transform(data_all)
    print(data_all)
    data = []
    for i in range(len(data_all) - sequence_length - 1):
        data.append(data_all[i: i + sequence_length + 1])
    reshaped_data = np.array(data).astype('float64')
    # np.random.shuffle(reshaped_data)
    #
    x = reshaped_data[:, :-1]
    y = reshaped_data[:, -1]
    split_boundary = int(reshaped_data.shape[0] * split)
    train_x = x[: split_boundary]
    test_x = x[split_boundary:]
    train_y = y[: split_boundary]
    test_y = y[split_boundary:]
    #train_x = x
    #train_y = y
    #test_x = x
    #test_y = y
    print("train_x.shape")
    print(train_x.shape)
    print(train_y.shape)
    print(test_x.shape)
    print(test_y.shape)


    return train_x, train_y, test_x, test_y


def build_model():
    # 
    model = Sequential()
    model.add(LSTM(input_shape=(None, 1), units=50, return_sequences=True))
    model.add(LSTM(100, return_sequences=False))
    model.add(Dense(units=1))
    model.add(Activation('linear'))

    model.compile(loss='mse', optimizer='rmsprop')
    return model


def train_model(train_x, train_y, test_x, test_y):
    model = build_model()

    try:
        early_stop = EarlyStopping(monitor='val_loss', patience=5)
        model.fit(train_x, train_y, batch_size=50, epochs=30,
                  validation_split=0.2, validation_data=(test_x, test_y), callbacks=[early_stop])

        model.save('model_on_10_off_20_count_3.h5')
        predict = model.predict(test_x)
        print(model.input.name)
        print(model.output.name)
        predict = np.reshape(predict, (predict.size,))
    except KeyboardInterrupt:
        print(predict)
        print(test_y)

    return predict, test_y


def MSE(y_predict, y_test):
    y_test = y_test.tolist()
    y_predict = y_predict.tolist()
    num = 0.0
    Size = len(y_test)
    for i in range(Size):
        d = abs(y_test[i][0] - y_predict[i][0])
        num = num + d * d
    mse = math.sqrt(num / Size)
    print(mse)
    return mse


def calAcc(y_predict, y_test):
    num = 0
    size = len(y_test)
    for i in range(size):
        tmp = int(y_predict[i] + 0.5)
        if tmp == y_test[i]:
            num = num + 1
    Acc = num / size
    print(Acc)
    return Acc


def saveData(test, predict, test_x, mse, acc):
    diff = predict - test
    npArray = np.hstack((test, predict, diff, test_x))
    strName = "./result" + "_" + str(sequence_length) + "_" + str(round(mse, 4)) + "_" + str(round(acc, 2)) + ".csv"
    np.savetxt(strName, npArray, fmt="%.3f", delimiter=",")

#预测模型制作

if __name__ == '__main__':
    train_x, train_y, test_x, test_y = load_data('pareto_on_10_off_20_count_3.csv')
    train_x = np.reshape(train_x, (train_x.shape[0], train_x.shape[1], 1))
    test_x = np.reshape(test_x, (test_x.shape[0], test_x.shape[1], 1))
    predict_y, test_y = train_model(train_x, train_y, test_x, test_y)
    print("===================")
    print(train_x.shape)
    print(test_x.shape)
    #predict_y = scaler.inverse_transform([[i] for i in predict_y])
    #test_y = scaler.inverse_transform(test_y)
    predict_y = np.array([[i] for i in predict_y])
    fig2 = plt.figure(2)
    plt.plot(predict_y[1000:1500], 'g-')
    plt.plot(test_y[1000:1500], 'r-')
    plt.legend(['predict', 'true'])
    plt.show()
    mse = MSE(predict_y, test_y)
    acc = calAcc(predict_y, test_y)
    test_x = np.reshape(test_x, (test_x.shape[0], test_x.shape[1]))
    saveData(test_y, predict_y, test_x, mse, acc)


